package com.kzj.service.impl;

import com.kzj.common.exception.MyException;
import com.kzj.common.result.Result;
import com.kzj.pojo.College;
import com.kzj.pojo.Course;
import com.kzj.pojo.CourseStudent;
import com.kzj.pojo.Student;
import com.kzj.pojo.dto.CourseStudentBatchAddDto;
import com.kzj.pojo.vo.CourseStudentVo;
import com.kzj.service.CourseStudentService;
import com.kzj.service.jpaRepository.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class CourseStudentServiceImpl implements CourseStudentService {
    @Autowired
    CourseStudentJpaRepository courseStudentJpaRepository;
    @Autowired
    CourseJpaRepository courseJpaRepository;
    @Autowired
    StudentJpaRepository studentJpaRepository;
    @Autowired
    CollegeJpaRepository collegeJpaRepository;
    @Autowired
    ScoreJpaRepository scoreJpaRepository;
    @Override
    public Result getAll()
    {
        return Result.success(getVo(courseStudentJpaRepository.findAll()));
    }
    @Override
    public Result getById(Long id)
    {
        return Result.success(courseJpaRepository.findById(id));
    }
    @Override
    public Result update(CourseStudent courseStudent)
    {
        if(scoreJpaRepository.getScoreByCourseStudentId(courseStudent.getId())!=null)
            throw new MyException("选课已录入成绩，修改失败");
        CourseStudent cs = courseStudentJpaRepository.getCourseStudentByCourseIdAndStudentId(courseStudent.getCourseId(), courseStudent.getStudentId());
        if(cs!=null&&!cs.getId().equals(courseStudent.getId()))
            throw  new MyException("学生已经选择了该课程");
        courseStudentJpaRepository.save(courseStudent);
        return Result.success();
    }
    @Override
    public Result add(CourseStudent courseStudent)
    {
        CourseStudent cs = courseStudentJpaRepository.getCourseStudentByCourseIdAndStudentId(courseStudent.getCourseId(), courseStudent.getStudentId());
        if(cs!=null)
            throw  new MyException("学生已经选择了该课程");
        courseStudentJpaRepository.save(courseStudent);
        return Result.success();
    }
    @Override
    public Result deleteById(Long id)
    {
        if(scoreJpaRepository.getScoreByCourseStudentId(id)!=null)
            throw new MyException("该选课已录入成绩,删除失败");
        courseStudentJpaRepository.deleteById(id);
        return Result.success();
    }
    @Override
    public Result batchAdd(CourseStudentBatchAddDto dto)
    {
        List<CourseStudent> list=new ArrayList<>();
        if(dto.getStudentId()!=null&&dto.getCourseIds()!=null)
        {
            for (Long courseId : dto.getCourseIds()) {
                list.add(CourseStudent.builder().studentId(dto.getStudentId()).courseId(courseId).term(dto.getTerm()).build());
            }
        }
        if(dto.getCourseId()!=null&&dto.getStudentIds()!=null)
        {
            for (Long studentId : dto.getStudentIds()) {
                list.add(CourseStudent.builder().studentId(studentId).courseId(dto.getCourseId()).term(dto.getTerm()).build());
            }
        }
        boolean b = list.stream().anyMatch(cs -> courseStudentJpaRepository.getCourseStudentByCourseIdAndStudentId(cs.getCourseId(), cs.getStudentId()) != null);
        if(b)
            throw new MyException("选课重复");
        courseStudentJpaRepository.saveAll(list);
        return Result.success();
    }
    @Override
    public Result getOptionalCoursesByStudentId(Long studentId)
    {
        List<CourseStudent> csList = courseStudentJpaRepository.getCourseStudentsByStudentId(studentId);
        if(csList.isEmpty())
            return Result.success(courseJpaRepository.findAll());
        List<Long> nonOptionalCIds  = csList.stream().map(CourseStudent::getCourseId).collect(Collectors.toList());
        return Result.success(courseJpaRepository.getCoursesByIdNotIn(nonOptionalCIds));

    }
    @Override
    public Result getOptionalStudentsByCourseId(Long courseId)
    {
        List<CourseStudent> csList = courseStudentJpaRepository.getCourseStudentsByCourseId(courseId);
        if(csList.isEmpty())
            return Result.success(studentJpaRepository.findAll());
        List<Long> nonOptionalSIds  = csList.stream().map(CourseStudent::getStudentId).collect(Collectors.toList());
        return Result.success(studentJpaRepository.getStudentsByIdNotIn(nonOptionalSIds));
    }
    @Override
    public Result batchDelete(String courseIds,String studentIds)
    {
        List<Long> cIds = Arrays.stream(courseIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        List<Long> sIds = Arrays.stream(studentIds.split(",")).map(Long::valueOf).collect(Collectors.toList());
        cIds.stream().forEach(cId -> sIds.stream().forEach(sId -> {
            CourseStudent cs = courseStudentJpaRepository.getCourseStudentByCourseIdAndStudentId(cId, sId);
            if(scoreJpaRepository.getScoreByCourseStudentId(cs.getId())!=null)
                throw new MyException("该选课已录入成绩,删除失败");
        }));
        cIds.stream().forEach(cId -> sIds.stream().forEach(sId -> courseStudentJpaRepository.deleteCourseStudentByCourseIdAndStudentId(cId,sId)));
        return Result.success();
    }
    @Override
    public Result getDeletableStudentsByCourseId(Long courseId)
    {
        List<Long> collect = courseStudentJpaRepository.getCourseStudentByCourseId(courseId).stream().map(CourseStudent::getStudentId).collect(Collectors.toList());
        return Result.success(studentJpaRepository.getStudentsByIdIn(collect));
    }
    @Override
    public Result getDeletableCoursesByStudentId(Long studentId)
    {
        List<Long> collect = courseStudentJpaRepository.getCourseStudentByStudentId(studentId).stream().map(CourseStudent::getCourseId).collect(Collectors.toList());
        return Result.success(courseJpaRepository.getCoursesByIdIsIn(collect));
    }
    @Override
    public Result terms()
    {
        return Result.success(Arrays.asList(2021,2022,2023,2024));
    }

    @Override
    public Result getCourseStudentByTeacherId(Long teacherId) {
        List<Course> courses = courseJpaRepository.getCoursesByTeacherId(teacherId);
        List<Long> courseIds = courses.stream().map(Course::getId).collect(Collectors.toList());
        return Result.success(getVo(courseStudentJpaRepository.getCourseStudentsByCourseIdIn(courseIds)));
    }

    private CourseStudentVo getVo(CourseStudent courseStudent)
    {
        Course course = courseJpaRepository.findById(courseStudent.getCourseId()).get();
        Student student=studentJpaRepository.findById(courseStudent.getStudentId()).get();
        College college = collegeJpaRepository.findById(course.getCollegeId()).get();
        CourseStudentVo vo = new CourseStudentVo();
        BeanUtils.copyProperties(courseStudent,vo);
        vo.setCollegeName(college.getName());
        vo.setCourseCode(course.getCode());
        vo.setCourseName(course.getName());
        vo.setStudentNo(student.getNo());
        vo.setStudentName(student.getFirstname()+" "+student.getLastname());
        return vo;
    }
    private List<CourseStudentVo> getVo(Iterable iterable)
    {
        List<CourseStudentVo> result=new ArrayList<>();
        Iterator iterator = iterable.iterator();
        while (iterator.hasNext())
        {
            result.add(getVo((CourseStudent) iterator.next()));
        }
        return result;
    }
}
